#pragma once
#include <string>
#include <vector>
#include <memory>
#include <sstream>
#include <fstream>
#include <iostream>
const std::string HttpSep = "\r\n";
const std::string BlankSep=" ";

const std::string homepage = "index.html";
const std::string wwwroot = "./wwwroot";

class HttpRequest
{
public:
    HttpRequest() : _req_blank(HttpSep), _path(wwwroot)
    {
    }

    bool GetLine(std::string &str, std::string *line)
    {
        auto pos = str.find(HttpSep);
        if (pos == std::string::npos)
            return false;
        *line = str.substr(0, pos);

        str.erase(0, pos + HttpSep.size());
        return true;
    }


    void DeSerialize(std::string &request)
    {
        std::string line;
        bool ok = GetLine(request, &line);
        if (!ok)
            return;
        _req_line = line;
        while (true)
        {
            bool ok = GetLine(request, &line);
            // 获取到报头
            if (ok && !line.empty())
            {
                _req_header.push_back(line);
            }
            // 读到正文
            else if (ok && line.empty())
            {
                _req_content = line;
            }
            else
                break;
        }
    }

    void HttpDebug()
    {
        std::cout << "_req_line:" << _req_line << std::endl;
        for (auto str : _req_header)
        {
            std::cout << "_req_header:" << str << std::endl;
        }
        std::cout << _req_blank << std::endl;

        std::cout << "_method:" << _method << std::endl;
        std::cout << "_url:" << _url << std::endl;
        std::cout << "_http_version:" << _http_version << std::endl;
    }

    std::string GetUrl() { return _url; }

    std::string GetPath() { return _path; }

    void ParseReqLine()
    {
        std::stringstream ss(_req_line);
        ss >> _method >> _url >> _http_version;

        if (_url == "/")
        {
            _path += _url;
            _path += homepage;
        }
        else
        {
            _path += _url;
        }
    }

    void ParseSuffix()
    {
        auto pos=_path.rfind(".");
        if(pos==std::string::npos)
            _suffix=".html";
        else
            _suffix=_path.substr(pos);
    }

    void Parse()
    {
        // 分析请求行
        ParseReqLine();
        //提取后缀
        ParseSuffix();
    }

    std::string GetFileContenHeader(const std::string &path)
    {
        std::ifstream in(path, std::ios::binary);
        if(!in.is_open())
            return "";
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        std::string content;
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);

        in.close();
        return content;


    }
    std::string GetFileContent()
    {
        return GetFileContenHeader(_path);
    }

    std::string Get_404()
    {
        return GetFileContenHeader("./wwwroot/404.html");
    }

    std::string GetSuffix(){return _suffix;}

    ~HttpRequest()
    {
    }

private:
    std::string _req_line;
    std::vector<std::string> _req_header;
    std::string _req_blank;
    std::string _req_content;

    // 解析内容
    std::string _method;
    std::string _url;
    std::string _http_version;
    std::string _path;
    std::string _suffix;
};


class HttpResponse
{
public:
    HttpResponse()
    :_http_version("HTTP/1.0"),_status_code(200),_status_code_desc("OK"),_resp_blank(HttpSep)
    {

    }

    void SetCode(int code)
    {
        _status_code=code;
    }

    void SetCodeDesc(std::string desc)
    {
        _status_code_desc=desc;
    }

    //version code desc
    void MakeStatusLine()
    {
        _status_line= _http_version+BlankSep+std::to_string(_status_code)+BlankSep+_status_code_desc+HttpSep;
    }

    void AddHeader(const std::string& header)
    {
        _resp_header.push_back(header);
    }

    void AddContent(const std::string& content)
    {
        _resp_content=content;
    }

    std::string Serizlizer()
    {
        std::string resp=_status_line;
        for(auto &header:_resp_header)
        {
            //默认是带上/r/n
            resp+=header;
        }
        resp+=_resp_blank;
        resp+=_resp_content;

        return resp;
    }
    ~HttpResponse(){}
private:
    std::string _status_line;
    std::vector<std::string> _resp_header;
    std::string _resp_blank;
    std::string _resp_content;

    std:: string _http_version;
    int _status_code;
    std::string _status_code_desc;
};

class Factory
{
public:
    std::shared_ptr<HttpRequest> BuildRequest()
    {
        std::shared_ptr<HttpRequest> req(new HttpRequest());
        return req;
    }

    std::shared_ptr<HttpResponse> BuildResPonse()
    {
        std::shared_ptr<HttpResponse> resp(new HttpResponse());
        return resp;
    }
};
